#pragma once

#include "base.h"
#include "../impl/ma_deriv.h"

namespace mdtx::online::updater
{
    template <typename T>
    class macd : public updater_base<T, T, 2, 3>,
                 public impl::macd<T>
    {
        using base = updater_base<T, T, 2, 3>;
        using ibase = impl::macd<T>;

    public:
        using typename base::tuple_in;
        using typename base::tuple_out;
        using base::insert;
        using base::remove;

        using ibase::ibase;
        using ibase::insert_impl;
        using ibase::reset_impl;

        explicit macd(ptrdiff_t period)
            : ibase(T(2) / (period + 1))
        {
        }

        void insert(tuple_in const &in) override
        {
            insert_impl(std::get<0>(in), std::get<1>(in));
        }

        void reset() override
        {
            reset_impl();
        }

        tuple_out get() override
        {
            return tuple_out(this->cd, this->sig, this->hist);
        }
    };

    template <typename T>
    class rsi : public updater_base<T, T, 2, 1>,
                public impl::rsi<T>
    {
        using base = updater_base<T, T, 2, 1>;
        using ibase = impl::rsi<T>;

    public:
        using typename base::tuple_in;
        using typename base::tuple_out;
        using base::insert;
        using base::remove;

        using ibase::ibase;
        using ibase::insert_impl;
        using ibase::reset_impl;

        explicit rsi(ptrdiff_t period)
            : ibase(T(2) / (period + 1))
        {
        }

        void insert(tuple_in const &in) override
        {
            insert_impl(std::get<0>(in), std::get<1>(in));
        }

        void reset() override
        {
            reset_impl();
        }

        tuple_out get() override
        {
            T ratio = 1 / (1 + this->m_gain / this->m_loss);
            return tuple_out(1 - ratio);
        }
    };
}
